#ifndef SCREEN_H
#define SCREEN_H

#include <string>
#include <iostream>

extern std::ostream& storeOn(std::ostream &, Screen &);
// extern BitMap& storeOn(BitMap &, Screen &);
class Screen
{
    // WindowMgr的成员可以访问Screen类的私有部分
    friend class WindowMgr;
    // friend void WindowMgr::clear(ScreenIndex);
    friend std::ostream& storeOn(std::ostream &, Screen &);
public:
    typedef std::string::size_type pos;
    Screen() = default;
    Screen(pos ht, pos wd, char c) : height(ht), width(wd), contents(ht * wd, c) {}
    Screen(pos ht, pos wd) : height(ht), width(wd), contents(ht * wd, ' ') {}

    // 根据对象是否是 const 重载了 display 函数
    Screen &dispaly(std::ostream &os)
    {
        do_display(os);
        return *this;
    }
    const Screen &dispaly(std::ostream &os) const
    {
        do_display(os);
        return *this;
    }

    Screen &set(char);
    Screen &set(pos, pos, char);
    char get() const { return contents[cursor]; } // 读取光标处的字符，隐式内联
    inline char get(pos ht, pos wd) const;        // 显式内联
    Screen &move(pos r, pos c);                   // 能在之后被设为内联
    void some_member() const;
    pos size() const;
private:
    // 该函数负责显示Screen的内容
    void do_display(std::ostream &os) const { os << contents; }
    mutable size_t access_ctr; // 即使在一个 const 对象内也能被修改
    pos cursor = 0;            // 光标的位置
    pos height = 0, width = 0; // 屏幕的高和宽
    std::string contents;      // 保存screen内容
};

inline Screen::pos Screen::size() const
{
    return height * width;
}

inline Screen &Screen::set(char c)
{
    contents[cursor] = c; // 设置当前光标所在位置的新值
    return *this;         // 将 this 对象作为左值返回
}

inline Screen &Screen::set(pos r, pos col, char ch)
{
    contents[r * width + col] = ch; // 设置给定位置的新值
    return *this;                   // 将 this 对象作为左值返回
}

inline Screen &Screen::move(pos r, pos c) // 可以在函数的定义处制定 inline
{
    pos row = r * width; // 计算行的位置
    cursor = row + c;    // 在行内将光标移动到指定的列
    return *this;        // 以左值的形式返回对象
}

char Screen::get(pos r, pos c) const // 在类的内部声明成 inline
{
    pos row = r * width;      // 计算行的位置
    return contents[row + c]; // 返回给定列的字符
}

void Screen::some_member() const
{
    ++access_ctr; // 保存一个计数值,用于记录成员函数被调用的次数
    // 该成员需要完成的其他工作
}

#endif